package github

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/spf13/viper"
	"go.uber.org/zap"
	oAuth2 "golang.org/x/oauth2"
	"golang.org/x/oauth2/github"
	"jk-time/webook/internal/domain"
	"jk-time/webook/internal/service"
	"jk-time/webook/pkg/migrator/events"
	"net/http"
)

type GitService struct {
	oauth2Config *oAuth2.Config
	client       *http.Client
	srv          service.UserService
	prooducer    events.Producer
}

func NewGitService(clientId, clientSecret string, srv service.UserService) *GitService {
	redirect := viper.GetString("oauth.git")

	//redirectURI := url.PathEscape(redirect)
	oauth2Config := &oAuth2.Config{
		ClientID:     clientId,
		ClientSecret: clientSecret,
		RedirectURL:  redirect,
		Scopes:       []string{"user:email"},
		Endpoint:     github.Endpoint,
	}
	return &GitService{
		oauth2Config: oauth2Config,
		client:       http.DefaultClient,
		srv:          srv,
	}
}
func (g GitService) AuthURL(ctx context.Context, state string) (string, error) {
	url := g.oauth2Config.AuthCodeURL(state, oAuth2.AccessTypeOnline)
	return url, nil
}

func (g GitService) VerifyCode(ctx context.Context, code string) (domain.Oauth2Info, error) {
	token, err := g.oauth2Config.Exchange(ctx, code)
	if err != nil {
		return domain.Oauth2Info{}, fmt.Errorf("oauth2 返回错误响应,错误码:%s,错误信息:%s", code, err.Error())
	}

	client := g.oauth2Config.Client(context.Background(), token)
	resp, err := client.Get("https://api.github.com/user")
	if err != nil {
		return domain.Oauth2Info{}, fmt.Errorf("oauth2 登录校验失败,错误信息:%s", err.Error())
	}
	defer resp.Body.Close()

	// 读取响应内容
	var userInfo map[string]interface{}
	if err := json.NewDecoder(resp.Body).Decode(&userInfo); err != nil {
		return domain.Oauth2Info{}, fmt.Errorf("json序列化失败:%d", err.Error())
	}

	github_id := userInfo["id"].(int64)
	node_id := userInfo["node_id"].(string)
	zap.L().Info("调用guthub，拿到用户信息",
		zap.Int64("github_id", github_id),
		zap.String("node_id", node_id))
	return domain.Oauth2Info{
		GithubId: github_id,
		NodeId:   node_id,
	}, nil
}

func (g GitService) FindOrCreateByInfo(ctx context.Context, info domain.Oauth2Info) (domain.User, error) {
	return g.srv.FindOrCreateGithub(ctx, info)
}
